package com.planw.beetl.sql.marker;

import com.intellij.codeInsight.daemon.RelatedItemLineMarkerInfo;
import com.intellij.codeInsight.daemon.RelatedItemLineMarkerProvider;
import com.intellij.codeInsight.navigation.NavigationGutterIconBuilder;
import com.intellij.openapi.editor.markup.GutterIconRenderer;
import com.intellij.psi.*;
import com.planw.beetl.utils.ContextIcons;
import com.planw.beetl.utils.JavaService;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.asJava.classes.KtUltraLightClass;

import java.util.*;

public class BeetlSqlMapperLineMarkerProvider extends RelatedItemLineMarkerProvider {

    /**
     * 通过 SqlResource 注解的方式查找sql文件
     *
     * @param classType
     * @return
     */
    protected String findSqlResourceName(PsiClass classType) {
        PsiAnnotation[] annotations = classType.getAnnotations();
        if (annotations == null) {
            return null;
        }
        for (PsiAnnotation annotation : annotations) {
            String qualifiedName = annotation.getQualifiedName();
            if (StringUtils.startsWithIgnoreCase(qualifiedName, "org.beetl.sql.") &&
                    StringUtils.endsWithIgnoreCase(qualifiedName, ".SqlResource")) {
                PsiAnnotationParameterList list = annotation.getParameterList();
                for (PsiNameValuePair attribute : list.getAttributes()) {
                    return attribute.getLiteralValue();
                }
            }

        }
        return null;
    }

    @Override
    protected void collectNavigationMarkers(@NotNull PsiElement element, @NotNull Collection<? super RelatedItemLineMarkerInfo<?>> result) {
        if (!(element instanceof PsiClass)) {
            return;
        }
        JavaService javaService = JavaService.getInstance(element.getProject());
        PsiClass psiClass = (PsiClass) element;
        if (!javaService.checkIsBeetlSqlClass(psiClass)) {
            return;
        }
        List<PsiFile> fileList = javaService.getAllBeetlSqlFiles(psiClass.getProject(), psiClass);
        if (fileList == null || fileList.isEmpty()) {
            return;
        }
        List<PsiElement> tgs = new LinkedList<>();
        for (PsiFile psiFile : fileList) {
            if(psiFile.getTextRange() != null){
                tgs.add(psiFile);
            }
        }
        if(!tgs.isEmpty()){
            NavigationGutterIconBuilder<PsiElement> builderMain =
                    NavigationGutterIconBuilder.create(ContextIcons.INJECTION)
                            .setAlignment(GutterIconRenderer.Alignment.LEFT)
                            .setTargets(tgs)
                            .setTooltipTitle("Navigation to target sql file");
            if(psiClass.getTextRange() != null){
                result.add(builderMain.createLineMarkerInfo(psiClass.getNameIdentifier()));
            } else if(psiClass instanceof KtUltraLightClass){
                result.add(builderMain.createLineMarkerInfo(((KtUltraLightClass) psiClass).getKotlinOrigin().getNameIdentifier()));
            }
        }
        PsiMethod[] psiMethods = psiClass.getMethods();
        if (psiMethods == null || psiMethods.length < 1) {
            return;
        }

        Map<String, PsiMethod> psiMethodMap = new HashMap<>();
        for (PsiMethod psiMethod : psiMethods) {
            psiMethodMap.put(psiMethod.getName(), psiMethod);
        }

        Map<String, List<PsiElement>> targetSqlElement = javaService.buildTargetPsiElement(fileList, psiMethodMap);
        for (Map.Entry<String, PsiMethod> entry : psiMethodMap.entrySet()) {
            String methodName = entry.getKey();
            if (!targetSqlElement.containsKey(methodName)) {
                continue;
            }

            List<PsiElement> targetSqlElList = targetSqlElement.get(methodName);
            if (targetSqlElList == null || targetSqlElList.isEmpty()) {
                continue;
            }

            // 过滤重复
            List<PsiElement> newSetElement = new LinkedList<>();
            Set<Integer> haveKeys = new HashSet<>();
            for (PsiElement psiElement : targetSqlElList) {
                if (haveKeys.contains(Integer.valueOf(psiElement.getTextOffset()))) {
                    continue;
                }
                haveKeys.add(Integer.valueOf(psiElement.getTextOffset()));
                newSetElement.add(psiElement);
            }


            PsiMethod psiMethod = entry.getValue();

            NavigationGutterIconBuilder<PsiElement> builder = NavigationGutterIconBuilder.create(ContextIcons.MAPPER_LINE_MARKER_ICON)
                    .setAlignment(GutterIconRenderer.Alignment.CENTER)
                    .setTargets(newSetElement)
                    .setTooltipTitle("Navigation to target in beetlsql " + newSetElement.get(0).getText());
            result.add(
                    builder.createLineMarkerInfo(((PsiNameIdentifierOwner) psiMethod).getNameIdentifier())
            );
        }
    }


}
